package process
import (
	"fmt"
	"encoding/binary"
	"encoding/json"
	"net"
	"go_code/projectExec2/common/message"
	"go_code/projectExec2/client/utils"
)

type UserProcess struct{
	//暂时不需字段
}
//关联一个用户登录的方法
//写一个函数，完成登录
func (up *UserProcess)Login(userid int,userpwd string)(err error){
	//1、连接到服务器端
	conn,err := net.Dial("tcp","localhost:8889")
	if err != nil{
		fmt.Println("net.Dial err :",err)
		return
	}
	//延时关闭
	defer conn.Close()

	//2、准备通过conn发送消息给服务器
	var mes message.Message
	mes.Type = message.LoginMesType
	//3、创建一个LoginMes 结构体
	var loginMes message.LoginMes
	loginMes.UserId = userid
	loginMes.UserPwd = userpwd
	//4、将loginMes进行序列化
	data,err := json.Marshal(loginMes)
	if err != nil{
		fmt.Println("json.Marshal err:",err)
		return
	}
	//5、把序列化后的[]byte转型在赋给data
	mes.Data = string(data)
	//6、将mes进行序列化
	data,err = json.Marshal(mes)
	if err != nil{
		fmt.Println("json.Marshal er:",err)
		return
	}
	//7、此时的data就是要发送的数据
	//先把data的长度发给服务器
	//先获取data的长度->转成表示长度的byte切片
	var pkgLen uint32 = uint32(len(data))
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[:],pkgLen)

	//发送长度
	n,err := conn.Write(buf[:])
	if n != 4 || err != nil{
		fmt.Println("conn.Write fail, err:",err)
		return
	}
	fmt.Println("客户端成功发送消息长度！量：",len(data),string(data))

	_,err = conn.Write(data)
	if err != nil{
		fmt.Println("conn.Write(data) fail, err:",err)
		return
	}
	//time.Sleep(time.Second * 10)
	//以下还需处理服务器返回的消息
	tf := &utils.Transfer{
		Conn : conn,
	}
	mes,err = tf.ReadPkg() //mes就是消息类型
	if err != nil{
		fmt.Println("readPkg(conn) fail err:",err)
		return
	}
	//将mes的Data部分分序列化成LoginResMes
	var loginResMes message.LoginResMes
	err = json.Unmarshal([]byte(mes.Data),&loginResMes)
	if loginResMes.Code == 200{
		fmt.Println("登陆成功~")
		//对当前用户实例进行赋值
		CurUser.Conn = conn
		CurUser.UserId = userid
		CurUser.UserStatus = message.UserOnline
		
		//遍历所有在线用户列表
		fmt.Println("当前在线用户列表如下：")
		for _,v := range loginResMes.UsersId{
			if v == userid{
				continue
			}
			fmt.Println("用户id:",v)

			//完成客户端的onlineUsers 完成初始化
			user := &message.User{
				UserId : v,
				UserStatus : message.UserOnline,
			}
			onlineUsers[v] = user
		}

		//这里还需要启动客户端协程
		//该协程保持和服务端通讯，如果服务器有数据推送给客户端
		//则可以接收并显示到客户端的终端
		go ServerProcessMes(conn)

		//调用登录成功后的菜单
		for {
			ShowMenu()
		}
	}else{
		fmt.Println(loginResMes.Error)
	}
	return nil
}

//写一个函数，完成注册
func (up *UserProcess)Registe(userid int,userpwd,nickname string)(err error){
	//1、连接到服务器端
	conn,err := net.Dial("tcp","localhost:8889")
	if err != nil{
		fmt.Println("net.Dial err :",err)
		return
	}
	//延时关闭
	defer conn.Close()

	//2、准备通过conn发送消息给服务器
	var mes message.Message
	mes.Type = message.RegisterMesType
	//3、创建一个LoginMes 结构体
	var registerMes message.RegisterMes
	registerMes.User.UserId = userid
	registerMes.User.UserPwd = userpwd
	registerMes.User.UserName = nickname
	//4、将registerMes进行序列化
	data,err := json.Marshal(registerMes)
	if err != nil{
		fmt.Println("json.Marshal(register) err:",err)
		return
	}
	//5、把序列化后的[]byte转型在赋给data
	mes.Data = string(data)
	//6、将mes进行序列化
	data,err = json.Marshal(mes)
	if err != nil{
		fmt.Println("json.Marshal er:",err)
		return
	}
	//先创建一个transfer实例
	tf := &utils.Transfer{
		Conn : conn,
	}
	//调用utils包的Writepkg方法
	err = tf.WritePkg(data)
	if err != nil{
		fmt.Println("Register WritePkg Error : ",err)
	}
	//
	//以下还需处理服务器返回的消息
	mes,err = tf.ReadPkg() //mes就是消息类型
	if err != nil{
		fmt.Println("Register readPkg(conn) fail err:",err)
		return
	}
	//将mes的Data部分分序列化成RegisterResMes
	var registerResMes message.RegisterResMes
	err = json.Unmarshal([]byte(mes.Data),&registerResMes)
	if registerResMes.Code == 200{
		fmt.Println("注册成功~可前往登录~")
	}else{
		fmt.Println(registerResMes.Error)
	}
	return nil
}